#pragma once
#include <iostream>
#include <string>
#include "socket.hpp"
#include <json/json.h>
#include <functional>
// 实现一个自定义网络版本的计算器
using namespace socketmodule;
using namespace logmodule;
// client->server发起请求
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char opera)
        : _x(x),
          _y(y),
          _opera(opera)
    {
    }
    std::string Serialiaze()
    {
        // 使用json组件序列化
        std::string s;
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["opera"] = _opera;
        Json::StreamWriterBuilder writer;
        s = Json::writeString(writer, root);
        return s;
    }
    bool Deserialize(std::string &line)
    {
        // Json::Value root;
        // Json::CharReaderBuilder builder;
        // std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        // return reader->parse(line.data(), line.data() + line.size(), &root, nullptr);
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(line, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _opera = root["opera"].asInt();
        }
        return ok;
    }
    int X() { return _x; }
    int Y() { return _y; }
    char Opera() { return _opera; }
    ~Request()
    {
    }

private:
    int _x;
    int _y;
    char _opera; // 运算符
};

// server->client服务器对客户端做出的回应
class Response
{
public:
    Response()
    {
    }
    std::string Serialiaze()
    {
        std::string s;
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StreamWriterBuilder writer;
        s = Json::writeString(writer, root);
        return s;
    }
    bool Deserialize(std::string &line)
    {
        // Json::Value root;
        // Json::CharReaderBuilder builder;
        // std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        // return reader->parse(line.data(), line.data() + line.size(), &root, nullptr);
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(line, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
    void setResult(int res)
    {
        _result = res;
    }
    void setCode(int code)
    {
        _code = code;
    }
    void showresult()
    {
        std::cout<<"结果是："<<_result<<"["<<_code<<"]"<<std::endl;
    }
    ~Response()
    {
    }

private:
    int _result; // 运算结果，还需要一个标志位来区分运算是否合法
    int _code;   // 用0来表示成功，1234均表示不同情况的异常
};
using func_t = std::function<Response(Request &req)>;
const std::string sep = "\r\n";
class Protocol
{
public:
    Protocol(func_t func) : _func(func)
    {
    }
    Protocol()
    {}
    std::string Encode(const std::string &jsonstr)
    {
        // 拿到了json串本身的长度
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep; // 相当于应用层封装报头
    }

    // 判断报文完整性
    // 包含过多请求，分析出一个完整请求，并从缓冲区中移除
    bool Decode(std::string &buffer, std::string *package)
    {
        // 找分隔符
        ssize_t pos = buffer.find(sep); // 找分隔符
        if (pos == std::string::npos)   // 分隔符都没有找到
        {
            return false;
        }
        std::string packagelen = buffer.substr(0, pos); // 从位置零到分割符之前的位置
        // 存储的是格式化串本身应该有的长度
        int packagelenInt = std::stoi(packagelen);                          // 将字符转化为int变量
        int targetlen = packagelen.size() + packagelenInt + 2 * sep.size(); // 传进来的报文应该具有的长度
        if (buffer.size() < targetlen)                                      // 如果传进来的报文长度没有应该具有的报文长度长的话，那么就返回一个假。
        {
            return false;
        }
        // 提取一个完整报文、
        *package = buffer.substr(pos + sep.size(), packagelenInt); // 从分隔符后面开始提取完整格式化字符串
        buffer.erase(0, targetlen);                                          // 删除前面的一个完整报文
        return true;                                                         // 返回一个真
    }
    void GetRequest(std::shared_ptr<Socket> &sock, inetaddr &client)
    {
        std::string inbuffer;
        while (true)
        {
            int n = sock->Recv(&inbuffer);
            if (n > 0)
            {
                // 解析报文，如果没有完整报文，就继续读
                std::string json_package;
                bool ret = Decode(inbuffer, &json_package);
                std::cout<<json_package<<std::endl;
                if (!ret)
                {
                    continue;
                }
                // 已经提取到了一个完整的报文
                Request req;
                bool ok = req.Deserialize(json_package);
               
                if (!ok)
                    continue;
                // 反序列化成功
                // 已经得到了一个反序列化的内部属性
                // 我们要完成计算，构建计算结果和结果编码
                // 不是协议中的内容，而是服务器中的业务
                Response resp = _func(req);
                // 得到了response
                // 将应答写给客户端，要先序列化
                std::string json_str = resp.Serialiaze();
                // 添加报文长度
                std::string send_str = Encode(json_str); // 携带长度的报文
                // 直接发送
                sock->Send(send_str);
            }
            else if (n == 0)
            {
                LOG(loglevel::INFO) << "clent:" << client.Stringaddr() << ",quit!";
                break;
            }
            else
            {
                LOG(loglevel::WARN) << "clent:" << client.Stringaddr() << ",receive error!";
                break;
            }
        }
    }
    bool Getresponse(std::shared_ptr<Socket> &client,std::string &resp_buffer,Response *resp)
    {
        // 面向字节流
        while (true)
        {
            int n = client->Recv(&resp_buffer);
            std::cout<<"yes e"<<std::endl;;
            if (n > 0)
            {
                std::cout<<"resp buffer-------"<<std::endl;
                std::cout<<resp_buffer<<std::endl;
                // 读取成功以后
                std::string json_package;
                bool ret = Decode(resp_buffer, &json_package);
                if (!ret)
                    continue;
                std::cout<<"Decode string--------"<<std::endl;
                std::cout<<json_package<<std::endl;
                resp->Deserialize(json_package); // 做完反序列化
                return true;
            }
            else if (n == 0)
            {
                std::cout<<"server quit"<<std::endl;
                return false;
            }
            else
            {
                std::cout<<"receving error"<<std::endl;
                return false;
            }
        }
    }
    std::string BuildQequeststring(int x, int y, char opera)
    {
        Request req(x, y, opera);

        // 序列化
        std::string json_str = req.Serialiaze();
        std::cout<<"building jsonstring-------"<<std::endl;
        std::cout<<json_str<<std::endl;
        return Encode(json_str);
    }
    ~Protocol()
    {
    }

private:
    Request _req;
    Response _resp;
    func_t _func;
};